package com.ruoyi.workbench.service.impl;

import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.workbench.constants.Constant;
import com.ruoyi.workbench.domain.WbVisitLogStatistics;
import com.ruoyi.workbench.domain.WbVisitLogStatisticsOne;
import com.ruoyi.workbench.domain.WbWholeUnit;
import com.ruoyi.workbench.mapper.WbVisitLogMapper;
import com.ruoyi.workbench.service.IWbVisitLogStatisticsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;

import static com.ruoyi.workbench.utils.Generator.getCommonCount;

/**
 * 上报统计Service业务层处理
 *
 * @author hanjiafeng
 * @date 2021-02-26
 */
@Service
@Slf4j
public class WbVisitLogStatisticsServiceImpl implements IWbVisitLogStatisticsService {
    private final ISysDeptService sysDeptService;
    private final WbVisitLogMapper wbVisitLogMapper;

    public WbVisitLogStatisticsServiceImpl(WbVisitLogMapper wbVisitLogMapper, ISysDeptService sysDeptService) {
        this.wbVisitLogMapper = wbVisitLogMapper;
        this.sysDeptService = sysDeptService;
    }

    /**
     * 查询上报统计列表
     *
     * @param wholeUnit wholeUnit
     * @param startTime startTime
     * @param endTime   endTime
     * @param period    周期选择
     * @return 上报统计
     */
    @Override
    @DataScope(deptAlias = "sd", userAlias = "su")
    public List<WbVisitLogStatistics> selectWbVisitLogStatisticsList(WbWholeUnit wholeUnit, String excludeType, Integer period, String startTime, String endTime) {

        List<WbVisitLogStatisticsOne> increaseList = wbVisitLogMapper.selectWbVisitLogStatisticsOne(wholeUnit, period, startTime, endTime);
        return trimList(wholeUnit, increaseList, excludeType, period);
    }

    @Override
    @DataScope(deptAlias = "sd", userAlias = "su")
    public List<WbVisitLogStatistics> selectChannelWbVisitLogStatisticsList(WbWholeUnit wholeUnit, String excludeType, Integer period, String startTime, String endTime) {

        List<WbVisitLogStatisticsOne> increaseList = wbVisitLogMapper.selectChannelWbVisitLogStatisticsOne(wholeUnit, period, startTime, endTime);
        return trimList(wholeUnit, increaseList, excludeType, period);
    }

    /**
     * 获取用户对应的部门
     *
     * @param wholeUnit wholeUnit
     * @return 部门
     */
    private SysDept getUserDept(WbWholeUnit wholeUnit) {
        SysUser sysUser = ShiroUtils.getSysUser();
        SysDept sysDept = sysDeptService.selectDeptById(sysUser.getDeptId());
        int level;
        //如果用户在根目录下，则用户等级为2，否则为逗号数量加3
        if (sysDept.getDeptId().equals(Constant.ROOT_DEPT_ID)) {
            level = Constant.UNIT_LEVEL_2;
        } else {
            level = getCommonCount(sysDept.getAncestors()) + 3;
        }
        switch (level) {
            case 2:
                break;
            case 3:
                if (Objects.isNull(wholeUnit.getUnit3())) {
                    wholeUnit.setUnit3(new SysDept());
                }
                break;
            case 4:
                if (Objects.isNull(wholeUnit.getUnit4())) {
                    wholeUnit.setUnit4(new SysDept());
                }
                break;
            case 5:
                if (Objects.isNull(wholeUnit.getUnit5())) {
                    wholeUnit.setUnit5(new SysDept());
                }
                break;
            default:
                throw new IllegalArgumentException("用户等级异常");
        }
        if (wholeUnit.getUnit6() != null) {
            sysDept = wholeUnit.getUnit6();
        } else if (wholeUnit.getUnit5() != null) {
            sysDept = wholeUnit.getUnit5();
        } else if (wholeUnit.getUnit4() != null) {
            sysDept = wholeUnit.getUnit4();
        } else if (wholeUnit.getUnit3() != null) {
            sysDept = wholeUnit.getUnit3();
        }
        return sysDept;
    }

    /**
     * 整理获取的统计单元
     *
     * @param wbWholeUnit  传入的部门
     * @param increaseList 统计list
     * @param excludeType  不包含的类型
     * @param period       周期
     * @return 整理后的单元
     */
    private List<WbVisitLogStatistics> trimList(WbWholeUnit wbWholeUnit, List<WbVisitLogStatisticsOne> increaseList, String excludeType, Integer period) {
        List<WbVisitLogStatistics> wbVisitLogStatisticsList = new ArrayList<>();
        SysDept sysDept = getUserDept(wbWholeUnit);
        sysDept.setPhone(excludeType);
        List<SysDept> deptList = sysDeptService.selectChildrenDept(sysDept);
        //添加新增合计
        AtomicLong increaseTotalCountAtomicLong = new AtomicLong(0);
        AtomicLong ownNetUserTotalCountAtomicLong = new AtomicLong(0);
        AtomicLong otherNetUserTotalCountAtomicLong = new AtomicLong(0);
        AtomicLong potentialUserTotalCountAtomicLong = new AtomicLong(0);
        AtomicLong transformedTotalCountAtomicLong = new AtomicLong(0);
        NumberFormat numberInstance = NumberFormat.getNumberInstance();
        numberInstance.setMaximumFractionDigits(2);
        //遍历新增
        increaseList.forEach(wbVisitLogStatisticsOne -> {
            WbVisitLogStatistics wbVisitLogStatistics = new WbVisitLogStatistics(period);
            //移除已经添加的部门
            for (int i = deptList.size() - 1; i >= 0; i--) {
                if (deptList.get(i).getDeptId() == wbVisitLogStatisticsOne.getUnitId()) {
                    deptList.remove(i);
                }
            }
            //设置负责人
            wbVisitLogStatistics.setPrincipal(wbVisitLogStatisticsOne.getPrincipal());
            //设置单元
            wbVisitLogStatistics.setUnitName(wbVisitLogStatisticsOne.getUnitName());
            //设置增加数量
            long increaseCount = wbVisitLogStatisticsOne.getIncreaseCount();
            long ownNetUser = wbVisitLogStatisticsOne.getOwnNetUserCount();
            long otherNetUser = wbVisitLogStatisticsOne.getOtherNetUserCount();
            long potentialUser = wbVisitLogStatisticsOne.getPotentialUserCount();
            long transformed = wbVisitLogStatisticsOne.getTransformedCount();
            increaseTotalCountAtomicLong.getAndAdd(increaseCount);
            ownNetUserTotalCountAtomicLong.getAndAdd(ownNetUser);
            otherNetUserTotalCountAtomicLong.getAndAdd(otherNetUser);
            potentialUserTotalCountAtomicLong.getAndAdd(potentialUser);
            transformedTotalCountAtomicLong.getAndAdd(transformed);
            //设置每个统计的数量
            wbVisitLogStatistics.setIncreaseCount(increaseCount);
            wbVisitLogStatistics.setOwnNetUserCount(ownNetUser);
            wbVisitLogStatistics.setOtherNetUserCount(otherNetUser);
            wbVisitLogStatistics.setPotentialUserCount(potentialUser);
            wbVisitLogStatistics.setTransformedCount(transformed);
            String transformedRate = numberInstance.format((double) transformed / increaseCount) + "%";
            wbVisitLogStatistics.setTransformedRate(transformedRate);
            wbVisitLogStatisticsList.add(wbVisitLogStatistics);
        });
        //合计
        WbVisitLogStatistics totalWbVisitLogStatistics = new WbVisitLogStatistics(period);
        totalWbVisitLogStatistics.setUnitName("合计");
        totalWbVisitLogStatistics.setIncreaseCount(increaseTotalCountAtomicLong.get());
        totalWbVisitLogStatistics.setOwnNetUserCount(ownNetUserTotalCountAtomicLong.get());
        totalWbVisitLogStatistics.setOtherNetUserCount(otherNetUserTotalCountAtomicLong.get());
        totalWbVisitLogStatistics.setPotentialUserCount(potentialUserTotalCountAtomicLong.get());
        totalWbVisitLogStatistics.setTransformedCount(transformedTotalCountAtomicLong.get());
        String transformedRate = "0%";
        if (increaseTotalCountAtomicLong.get() != 0) {
            transformedRate = numberInstance.format((double) transformedTotalCountAtomicLong.get() / increaseTotalCountAtomicLong.get()) + "%";
        }
        totalWbVisitLogStatistics.setTransformedRate(transformedRate);
        wbVisitLogStatisticsList.add(0, totalWbVisitLogStatistics);
        deptList.forEach(tempDept -> {
            WbVisitLogStatistics wbVisitLogStatistics = new WbVisitLogStatistics(period);
            wbVisitLogStatistics.setUnitName(tempDept.getDeptName());
            wbVisitLogStatistics.setPrincipal(tempDept.getLeader());
            wbVisitLogStatistics.setTransformedRate("0%");
            wbVisitLogStatisticsList.add(wbVisitLogStatistics);
        });
        return wbVisitLogStatisticsList;
    }
}
